#include <stdio.h>
#include <stdlib.h>

#define MAX_LENGTH 100 //结构体可以存放的学生信息最大个数，不可变变量
//学生信息结构体数组，最多可以存放100个学生信息
struct student
{
    int id;               //学号
    char *name;           //姓名
    int age;              //年龄
    float c_score;        //C语言成绩
    float english_score;  //英语成绩
    float database_score; //数据库成绩
    float total_score;    //总分
} student_array[MAX_LENGTH];

//学生信息数量
int student_count = 0;

//函数声明
void print_all_students();                  //输出所有学生信息函数
void input_info();                          //录入信息函数
void query_info();                          //查询信息函数
void modify_info();                         //修改信息选择函数
void delete_info();                         //删除选择函数
void compute_total_score();                 //计算总分函数
void sort_info();                           //排序选择函数
int search_one_student();                   //定位学号函数
void print_one_student(struct student one); //输出一个学生信息函数
void delete_one_student(int student_index); //删除对应序号学生信息函数
char *get_item_name(int item_index);
void modify_one_student(int student_index); //执行修改信息函数
void sort_by_id();                          //学号排序函数
void sort_by_c_score();                     //C成绩排序函数
void sort_by_english_score();               //英语成绩排序函数
void sort_by_database_score();              //数据库成绩排序函数

// 主函数
int main()
{
    while (1)
    {
        printf("please select your operation：\n\n");
        printf("录入信息，请输入1，然后回车！\n\n");
        printf("查询信息，请输入2，然后回车！\n\n");
        printf("修改信息，请输入3，然后回车！\n\n");
        printf("删除信息，请输入4，然后回车！\n\n");
        printf("计算总分，请输入5，然后回车！\n\n");
        printf("排序信息，请输入6，然后回车！\n\n");
        printf("输出全部，请输入0，然后回车！\n\n");
        printf("退出程序，请输入-1，然后回车！\n");
        //函数选择变量
        int function = 0;
        //输入选择的函数编号值
        scanf("%d", &function);
        //根据输入的函数编号，执行对应的功能
        switch (function)
        {
        case -1:
            exit(1);
        case 0:
            print_all_students();
            break;
        case 1:
            input_info();
            break;
        case 2:
            query_info();
            break;
        case 3:
            modify_info();
            break;
        case 4:
            delete_info();
            break;
        case 5:
            compute_total_score();
            break;
        case 6:
            sort_info();
            break;
        default:
            printf("请输入正确的功能编号！！！\n\n");
            break;
        }
    }
    return 0;
}

//录入信息函数
void input_info()
{
    printf("当前功能————录入信息！\n");
    //判断是否还有空间
    if (student_count < MAX_LENGTH)
    {
        //声明一些临时变量
        int id = 0;
        char *name = (char *)malloc(100);
        int age = 0;
        float c_score = 0;
        float english_score = 0;
        float database_score = 0;
        printf("请输入学生信息\n");
        printf("学号：");
        scanf("%d", &id);
        printf("姓名：");
        scanf("%s", name);
        printf("年龄：");
        scanf("%d", &age);
        printf("C语言成绩：");
        scanf("%f", &c_score);
        printf("英语成绩：");
        scanf("%f", &english_score);
        printf("数据库成绩：");
        scanf("%f", &database_score);
        printf("学生信息校对：学号：%d,姓名：%s,年龄：%d,C语言成绩:%f,英语成绩：%f,数据库成绩：%f\n", id, name, age, c_score, english_score, database_score);
        //学生信息加入结构体数组
        student_array[student_count].id = id;
        student_array[student_count].name = name;
        student_array[student_count].age = age;
        student_array[student_count].c_score = c_score;
        student_array[student_count].english_score = english_score;
        student_array[student_count].database_score = database_score;
        student_count++;
        //是否继续录入信息
        printf("是否继续录入信息？继续请输入y,返回主菜单输入n\n");
        char go_on;
        scanf("%s", &go_on);
        if (go_on == 'y')
        {
            input_info();
        }
    }
    else
    {
        printf("学生结构体数据已满，可以删除一部分学生信息！\n");
    }
}

//查询信息函数
void query_info()
{
    printf("当前功能————查询信息！\n");
    printf("请输入学生的学号\n");
    int id = 0;
    scanf("%d", &id);
    //查找输入id学生的序号
    int student_index = search_one_student(id);
    if (student_index != -1)
    {
        print_one_student(student_array[student_index]);
    }
    else
    {
        printf("没有该学号的学生！\n");
    }
    //是否继续查询信息
    printf("是否继续查询信息？继续请输入y,返回主菜单输入n\n");
    char go_on;
    scanf("%s", &go_on);
    if (go_on == 'y')
        query_info();
}

//修改信息函数
void modify_info()
{
    printf("当前功能————修改信息！\n");
    printf("请输入学生的学号\n");
    int id = 0;
    scanf("%d", &id);
    //查找输入id学生的序号
    int student_index = search_one_student(id);
    if (student_index != -1)
    {
        modify_one_student(student_index);
    }
    else
    {
        printf("没有该学号的学生！\n");
    }
}

//删除信息函数
void delete_info()
{
    printf("当前功能————删除信息！\n");
    printf("请输入学生的学号\n");
    int id = 0;
    scanf("%d", &id);
    //查找输入id学生的序号
    int student_index = search_one_student(id);
    if (student_index != -1)
    {
        //防止student_index被改变，传入temp_index计算
        int temp_index = student_index;
        print_one_student(student_array[temp_index]);
        //删除前进行确认
        printf("确定删除学号 %d 同学的信息？继续请输入y\n", id);
        char be_true;
        scanf("%s", &be_true);
        if (be_true == 'y')
        {
            printf("%d\n", student_index);
            //执行删除动作
            delete_one_student(student_index);
        }
    }
    else
    {
        printf("没有该学号的学生！\n");
    }
    //是否继续删除信息
    printf("是否继续删除信息？继续请输入y,返回主菜单输入n\n");
    char go_on;
    scanf("%s", &go_on);
    if (go_on == 'y')
        delete_info();
}

//计算总分函数
void compute_total_score()
{
    int i;
    printf("当前功能————计算总分！\n");
    for (i = 0; i < student_count; ++i)
    {
        student_array[i].total_score = student_array[i].c_score + student_array[i].english_score + student_array[i].database_score;
        print_one_student(student_array[i]);
        printf("总成绩：%f\n", student_array[i].total_score);
    }
    printf("总分计算完成！！！\n");
}

//成绩排序函数
void sort_info()
{
    printf("当前功能————成绩排序！\n");
    printf("排序前所有学生信息如下：\n");
    print_all_students();
    int sort_type;
    while (1)
    {
        printf("请输入排序字段，学号：1,C语言成绩:2,英语成绩：3,数据库成绩：4\n");
        scanf("%d", &sort_type);
        if (sort_type >= 1 && sort_type <= 4)
            break;
    }
    switch (sort_type)
    {
    case 1:
        sort_by_id();
        break;
    case 2:
        sort_by_c_score();
        break;
    case 3:
        sort_by_english_score();
        break;
    case 4:
        sort_by_database_score();
        break;
    }
    printf("排序后所有学生信息如下：\n");
    print_all_students();
    //是否继续排序信息
    printf("是否继续排序信息？继续请输入y,返回主菜单输入n\n");
    char go_on;
    scanf("%s", &go_on);
    if (go_on == 'y')
        sort_info();
}

//根据输入的学号，遍历结构体数组，若存在该学生，返回数组下标，不存在返回-1
int search_one_student(int id)
{
    int i;
    for (i = 0; i < student_count; ++i)
    {
        if (student_array[i].id == id)
        {
            return i;
        }
    }
    return -1;
}

//输出某个学生的信息
void print_one_student(struct student one)
{
    printf("学生信息：学号：%d,姓名：%s,年龄：%d,C语言成绩:%f,英语成绩：%f,数据库成绩：%f\n", one.id, one.name, one.age, one.c_score, one.english_score, one.database_score);
}

//输出所有学生的信息
void print_all_students()
{
    int i;
    if (student_count == 0)
    {
        printf("暂无学生信息\n\n\n");
    }
    for (i = 0; i < student_count; ++i)
    {
        print_one_student(student_array[i]);
    }
}

void modify_one_student(int student_index)
{
    //修改前，输出学生信息
    print_one_student(student_array[student_index]);
    //字段序号初始值
    int item_index = 0;
    //不允许修改学号字段
    while (1)
    {
        printf("请输入要修改的字段序号，姓名：1,年龄：2,C语言成绩:3,英语成绩：4,数据库成绩：5\n");
        scanf("%d", &item_index);
        if (item_index >= 1 && item_index <= 5)
            break;
    }
    switch (item_index)
    {
    case 1:
        printf("请输入 %s 字段的新值\n", get_item_name(item_index));
        char *item_value_1 = (char *)malloc(100);
        ;
        scanf("%s", item_value_1);
        student_array[student_index].name = item_value_1;
        break;
    case 2:
        printf("请输入 %s 字段的新值\n", get_item_name(item_index));
        int item_value_2;
        scanf("%d", &item_value_2);
        student_array[student_index].age = item_value_2;
        break;
    case 3:
        printf("请输入 %s 字段的新值\n", get_item_name(item_index));
        float item_value_3;
        scanf("%f", &item_value_3);
        student_array[student_index].c_score = item_value_3;
        break;
    case 4:
        printf("请输入 %s 字段的新值\n", get_item_name(item_index));
        float item_value_4;
        scanf("%f", &item_value_4);
        student_array[student_index].english_score = item_value_4;
        break;
    case 5:
        printf("请输入 %s 字段的新值\n", get_item_name(item_index));
        float item_value_5;
        scanf("%f", &item_value_5);
        student_array[student_index].database_score = item_value_5;
        break;
    }
    printf("修改成功！新的学生信息如下：\n");
    //修改后输出学生信息
    print_one_student(student_array[student_index]);
    //是否继续修改信息
    printf("是否继续修改该学生信息？继续请输入y,返回主菜单输入n\n");
    char go_on;
    scanf("%s", &go_on);
    if (go_on == 'y')
        modify_one_student(student_index);
}

//删除数组对应序号的学生信息，把i位置后面的数据组元素向前移动覆盖i，student_count计数器减1
void delete_one_student(int student_index)
{
    int i;
    for (i = student_index; i < student_count - 1; ++i)
    {
        student_array[i] = student_array[i + 1];
    }
    student_count--;
    printf("删除完成\n\n\n");
}

//根据输入的字段序号，返回字段名称
char *get_item_name(int item_index)
{
    switch (item_index)
    {
    case 0:
        return "学号";
    case 1:
        return "姓名";
    case 2:
        return "年龄";
    case 3:
        return "C语言成绩";
    case 4:
        return "英语成绩";
    case 5:
        return "数据库成绩";
    default:
        return "";
    }
}

//按照id排序，使用最简单的冒泡排序法
void sort_by_id()
{
    int i, j;
    for (i = 0; i < student_count; ++i)
    {
        for (j = i; j < student_count; ++j)
        {
            if (student_array[i].id > student_array[j].id)
            {
                struct student temp = student_array[i];
                student_array[i] = student_array[j];
                student_array[j] = temp;
            }
        }
    }
    printf("按照 学号 排序完成\n");
}

//按照C语言成绩排序，使用最简单的冒泡排序法
void sort_by_c_score()
{
    int i, j;
    for (i = 0; i < student_count; ++i)
    {
        for (j = i; j < student_count; ++j)
        {
            if (student_array[i].c_score > student_array[j].c_score)
            {
                struct student temp = student_array[i];
                student_array[i] = student_array[j];
                student_array[j] = temp;
            }
        }
    }
    printf("按照 C语言成绩 排序完成\n");
}

//按照英语成绩排序，使用最简单的冒泡排序法
void sort_by_english_score()
{
    int i, j;
    for (i = 0; i < student_count; ++i)
    {
        for (j = i; j < student_count; ++j)
        {
            if (student_array[i].english_score > student_array[j].english_score)
            {
                struct student temp = student_array[i];
                student_array[i] = student_array[j];
                student_array[j] = temp;
            }
        }
    }
    printf("按照 英语成绩 排序完成\n");
}

//按照数据库成绩排序，使用最简单的冒泡排序法
void sort_by_database_score()
{
    int i, j;
    for (i = 0; i < student_count; ++i)
    {
        for (j = i; j < student_count; ++j)
        {
            if (student_array[i].database_score > student_array[j].database_score)
            {
                struct student temp = student_array[i];
                student_array[i] = student_array[j];
                student_array[j] = temp;
            }
        }
    }
    printf("按照 数据库成绩 排序完成\n");
}
